//
//  TTCache.m
//  Tint
//
//  Created by Kevin Wu on 8/23/12.
//  Copyright (c) 2012 Telligenty. All rights reserved.
//

#import "TTCache.h"


@implementation TTCache


#pragma mark - Accessors

@synthesize defaultTimeoutInterval = _defaultTimeoutInterval;



#pragma mark - Memory

- (id)init
{
    self = [super init];
    if ( self ) {
        _defaultTimeoutInterval = TTTimeIntervalWeek();
        
        _cacheDictionary = nil;
        
        _executeLock = [[NSLock alloc] init];
    }
    return self;
}

- (void)dealloc
{
    _defaultTimeoutInterval = 0.0;
    
    TTRelease(_cacheDictionary);
    
    TTRelease(_executeLock);
    
    [super dealloc];
}



#pragma mark - Public


+ (TTCache *)sharedObject
{
    return nil;
}

+ (BOOL)hasSharedObject
{
    return NO;
}

+ (void)destroySharedObject
{
}



- (BOOL)hasCacheForKey:(NSString *)key
{
    return [self hasCacheForKey:key name:TTCacheNameDefault];
}

- (BOOL)hasCacheForKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    BOOL valid = [self isItemValid:item];
    [_executeLock unlock];
    return valid;
}


- (void)removeCacheForKey:(NSString *)key
{
    [self removeCacheForKey:key name:TTCacheNameDefault];
}

- (void)removeCacheForKey:(NSString *)key name:(NSString *)name
{
}



- (void)cleanAllCache
{
}

- (void)cleanCache
{
    [self cleanCacheByName:TTCacheNameDefault];
}

- (void)cleanCacheByName:(NSString *)name
{
}


- (void)clearAllCache
{
}

- (void)clearCache
{
    [self clearCacheByName:TTCacheNameDefault];
}

- (void)clearCacheByName:(NSString *)name
{
}



- (NSUInteger)totalCount
{
    [_executeLock lock];
    int count = 0;
    for ( NSDictionary *cache in [_cacheDictionary objectEnumerator] ) {
        count += [cache count];
    }
    [_executeLock unlock];
    return count;
}

- (NSUInteger)count
{
    return [self countOfName:TTCacheNameDefault];
}

- (NSUInteger)countOfName:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSUInteger count = [cache count];
    [_executeLock unlock];
    return count;
}


- (NSArray *)cacheNames
{
    [_executeLock lock];
    NSArray *names = [_cacheDictionary allKeys];
    [_executeLock unlock];
    return names;
}

- (NSArray *)cacheItemKeys
{
    return [self cacheItemKeysOfName:TTCacheNameDefault];
}

- (NSArray *)cacheItemKeysOfName:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSArray *keys = [cache allKeys];
    [_executeLock unlock];
    return keys;
}





- (NSDate *)addDateOfKey:(NSString *)key
{
    return [self addDateOfKey:key name:TTCacheNameDefault];
}

- (NSDate *)addDateOfKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    NSDate *addDate = [item objectForKey:TTCacheItemAddDate];
    [_executeLock unlock];
    return addDate;
}


- (NSDate *)updateDateOfKey:(NSString *)key
{
    return [self updateDateOfKey:key name:TTCacheNameDefault];
}

- (NSDate *)updateDateOfKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    NSDate *updateDate = [item objectForKey:TTCacheItemUpdateDate];
    [_executeLock unlock];
    return updateDate;
}


- (NSDate *)expirationDateOfKey:(NSString *)key
{
    return [self expirationDateOfKey:key name:TTCacheNameDefault];
}

- (NSDate *)expirationDateOfKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    NSDate *expirationDate = [item objectForKey:TTCacheItemExpirationDate];
    [_executeLock unlock];
    return expirationDate;
}


- (NSString *)filePathOfKey:(NSString *)key
{
    return [self filePathOfKey:key name:TTCacheItemFilePath];
}

- (NSString *)filePathOfKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    NSString *filePath = [item objectForKey:TTCacheItemFilePath];
    [_executeLock unlock];
    return filePath;
}


- (int)fileSizeOfKey:(NSString *)key
{
    return [self fileSizeOfKey:key name:TTCacheNameDefault];
}

- (int)fileSizeOfKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    int fileSize = [[item objectForKey:TTCacheItemFileSize] intValue];
    [_executeLock unlock];
    return fileSize;
}


- (id)cacheObjectOfKey:(NSString *)key
{
    return [self cacheObjectOfKey:key name:TTCacheNameDefault];
}

- (id)cacheObjectOfKey:(NSString *)key name:(NSString *)name
{
    [_executeLock lock];
    NSDictionary *cache = [_cacheDictionary objectForKey:name];
    NSDictionary *item = [cache objectForKey:key];
    id object = [item objectForKey:TTCacheItemCacheObject];
    [_executeLock unlock];
    return object;
}



- (NSMutableDictionary *)addItemWithKey:(NSString *)key name:(NSString *)name timeoutInterval:(NSTimeInterval)timeoutInterval
{
    if ( key && name ) {
        
        NSMutableDictionary *cache = [_cacheDictionary objectForKey:name];
        if ( cache ) {
            
            NSDate *now = [[NSDate alloc] init];
            
            NSMutableDictionary *item = [cache objectForKey:key];
            if ( item == nil ) {
                NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
                [cache setObject:dict forKey:key];
                TTRelease(dict);
                
                item = [cache objectForKey:key];
                [item setObject:now forKey:TTCacheItemAddDate];
            }
            
            [item setObject:key forKey:TTCacheItemKey];
            
            [item setObject:now forKey:TTCacheItemUpdateDate];
            
            if ( timeoutInterval > 0.0 ) {
                [item setObject:[now dateByAddingTimeInterval:timeoutInterval] forKey:TTCacheItemExpirationDate];
            } else {
                [item removeObjectForKey:TTCacheItemExpirationDate];
            }
            
            TTRelease(now);
            
            return item;
            
        }
        
    }
    return nil;
}

- (BOOL)createCacheForName:(NSString *)name
{
    if ( name ) {
        
        if ( ![_cacheDictionary hasKeyEqualTo:name] ) {
            NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
            [_cacheDictionary setObject:dict forKey:name];
            TTRelease(dict);
        }
        
        return YES;
    }
    return NO;
}

- (BOOL)isItemValid:(NSDictionary *)item
{
    if ( item ) {
        NSDate *expirationDate = [item objectForKey:TTCacheItemExpirationDate];
        if ( expirationDate == nil ) {
            return YES;
        }
        NSDate *now = [[NSDate alloc] init];
        BOOL valid = [now isEarlierThanDate:expirationDate];
        TTRelease(now);
        return valid;
    }
    return NO;
}

@end
